﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using ManagedUIFlow.Infrastructure.Flows.Configuration;

namespace ManagedUIFlow.Infrastructure.Flows
{
    public static class XmlFlowFactory
    {
        public static readonly IList<Flow> Flows;             

        static XmlFlowFactory()
        {
            Flows = new List<Flow>();

            var configSection = GetConfiguration("Flow.config");

            foreach (FlowConfigurationElementCollection scenarioConfig in configSection.Scenarios)
                Flows.Add(CreateFlow(scenarioConfig));
        }

        static Flow CreateFlow(FlowConfigurationElementCollection flowConfig)
        {
            var flow = new Flow(flowConfig.Flow, 
                                flowConfig.Initiate, flowConfig.Redirectable, flowConfig.RedirectUrl);
             
            foreach (GivenConfigurationElementCollection navigationConfig in flowConfig)
                flow.Navigations.Add(CreateNavigation(navigationConfig));   
     
            return flow;
        }

        static Navigation CreateNavigation(GivenConfigurationElementCollection navigationConfig)
        {            
            
            var navigation = new Navigation(navigationConfig.Name, GetNavigationType(navigationConfig));

            foreach (WhenConfigurationElement transitionConfig in navigationConfig)
                navigation.Transitions.Add(CreateTransition(transitionConfig));             

            return navigation;
        }

        static Transition CreateTransition(WhenConfigurationElement transitionConfig)
        {
            var state = !string.IsNullOrEmpty(transitionConfig.Action)
                            ? transitionConfig.Action
                            : (!string.IsNullOrEmpty(transitionConfig.SubFlow)
                                   ? transitionConfig.SubFlow
                                   : transitionConfig.View);

            return new Transition(state, transitionConfig.NavigateTo);
        }

        private static NavigationType GetNavigationType(GivenConfigurationElementCollection navigationConfig)
        {
            foreach (WhenConfigurationElement transitionConfig in navigationConfig)
            {                
                return !string.IsNullOrEmpty(transitionConfig.Action)
                           ? NavigationType.ControllerAction
                           : (!string.IsNullOrEmpty(transitionConfig.SubFlow)
                                  ? NavigationType.SubFlow
                                  : NavigationType.RenderView);                
            }

            return NavigationType.EndFlow;
        }

        private static XmlFlowsConfigurationSection GetConfiguration(string configFilePath)
        {
            XmlFlowsConfigurationSection configuration;
            var context = System.Web.HttpContext.Current;

            if (context != null)
            {
                configuration = (XmlFlowsConfigurationSection) ConfigurationManager.GetSection("flowConfiguration");                
            }
            else
            {
                throw new InvalidOperationException("HttpContext unavailable");
                //configuration = (XmlFlowsConfigurationSection)GetConfigurationForCustomFile(string.Format("{0}\\{1}", context.Server.MapPath("~"), configFilePath)).GetSection("flowConfiguration");
            }
            
            return configuration;}

        private static System.Configuration.Configuration GetConfigurationForCustomFile(string fileName)
        {
            var fileMap = new ExeConfigurationFileMap {ExeConfigFilename = fileName};
            File.SetAttributes(fileMap.ExeConfigFilename, FileAttributes.Normal);
            return ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        }
    }
}